﻿using System;
using System.Collections.Generic;
using System.Text;
using Wangzeran.CodeMaker.Core.Tag;
using Wangzeran.CodeMaker.Core.Model;
using Wangzeran.CodeMaker.Core.DB;
using Wangzeran.CodeMaker.Core.Util;
using Wangzeran.CodeMaker.PlugIns.Util;

namespace Wangzeran.CodeMaker.PlugIns.Tags
{
    /// <summary>
    /// 值标签
    /// </summary>
    public class ValueTag : TagSupport
    {

        #region 标签属性字段

        /// <summary>
        /// 名称属性
        /// </summary>
        private const string ATTR_NAME = "name";
        /// <summary>
        /// 类型属性
        /// </summary>
        private const string ATTR_TYPE = "type";
        /// <summary>
        /// 关键字
        /// </summary>
        private const string ATTR_KEY = "key";
        /// <summary>
        /// 命名规则
        /// </summary>
        private const string ATTR_RULE = "rule";
        /// <summary>
        /// 前缀
        /// </summary>
        private const string ATTR_PREFIX = "prefix";
        /// <summary>
        /// 后缀
        /// </summary>
        private const string ATTR_SUFFIX = "suffix";
        /// <summary>
        /// 长度
        /// </summary>
        private const string ATTR_LENGTH = "length";
        /// <summary>
        /// 替换
        /// </summary>
        private const string ATTR_REPLACE = "replace";

        #endregion


        #region 属性值

        /// <summary>
        /// 基本数据类型
        /// </summary>
        private const string VALUE_BASIC = "basic";
        /// <summary>
        /// 引用数据类型
        /// </summary>
        private const string VALUE_REFERENCE = "reference";
        /// <summary>
        /// 原始类型
        /// </summary>
        private const string VALUE_ORIGINAL = "original";

        // 命名规则
        private const string VALUE_RULE_UPPER = "upper";
        private const string VALUE_RULE_LOWER = "lower";
        private const string VALUE_RULE_CAMEL = "camel";
        private const string VALUE_RULE_PASCAL = "pascal";

        // 列信息
        private const string VALUE_COLUMN_COLUMNNAME = "columnname";
        private const string VALUE_COLUMN_COLUMNTYPE = "columntype";
        private const string VALUE_COLUMN_COLUMNDESCRIPTION = "columndescription";
        private const string VALUE_COLUMN_REFERENCETABLENAME = "referencetablename";
        private const string VALUE_COLUMN_COLUMNLENGTH = "columnlength";
        private const string VALUE_COLUMN_TABLENAME = "tablename";

        // 表信息
        private const string VALUE_TABLE_TABLENAME = "tablename";
        private const string VALUE_TABLE_TABLEDESCRIPTION = "tabledescription";
        private const string VALUE_TABLE_REFERENCECOLUMN = "referencecolumn";

        #endregion


        /// <summary>
        /// 属性处理事件
        /// </summary>
        /// <param name="sb">StringBuilder</param>
        /// <param name="value">值</param>
        /// <typeparam name="T">类型</typeparam>
        public delegate void ProcessHandler<T>(StringBuilder sb, T value);

        /// <summary>
        /// 属性处理集合
        /// </summary>
        private IDictionary<string, ProcessHandler<object>> dicProcessProperties = null;
        /// <summary>
        /// 获取属性处理集合
        /// </summary>
        public IDictionary<string, ProcessHandler<object>> DicProcessProperties
        {
            get
            {
                if (dicProcessProperties == null)
                {
                    dicProcessProperties = new Dictionary<string, ProcessHandler<object>>();
                    // 属性
                    dicProcessProperties.Add(ATTR_PREFIX, ProcessPrefix);
                    dicProcessProperties.Add(ATTR_SUFFIX, ProcessSuffix);
                    dicProcessProperties.Add(ATTR_LENGTH, ProcessLength);
                    dicProcessProperties.Add(ATTR_REPLACE, ProcessReplace);
                    dicProcessProperties.Add(ATTR_RULE, ProcessRules);
                    // 命名规则值
                    dicProcessProperties.Add(VALUE_RULE_UPPER, ProcessRulesUpper);
                    dicProcessProperties.Add(VALUE_RULE_LOWER, ProcessRulesLower);
                    dicProcessProperties.Add(VALUE_RULE_CAMEL, ProcessRulesCamel);
                    dicProcessProperties.Add(VALUE_RULE_PASCAL, ProcessRulesPascal);
                }
                return this.dicProcessProperties;
            }
        }

        /// <summary>
        /// 处理列信息
        /// </summary>
        private IDictionary<string, ProcessHandler<ColumnModal>> dicProcessColumn = null;
        /// <summary>
        /// 获取处理列信息集合
        /// </summary>
        public IDictionary<string, ProcessHandler<ColumnModal>> DicProcessColumn
        {
            get
            {
                if (dicProcessColumn == null)
                {
                    dicProcessColumn = new Dictionary<string, ProcessHandler<ColumnModal>>();
                    dicProcessColumn.Add(VALUE_COLUMN_COLUMNNAME, ProcessColumnName);
                    dicProcessColumn.Add(VALUE_COLUMN_COLUMNTYPE, ProcessColumnType);
                    dicProcessColumn.Add(VALUE_COLUMN_COLUMNDESCRIPTION, ProcessColumnDescription);
                    dicProcessColumn.Add(VALUE_COLUMN_TABLENAME, ProcessColumnTableName);
                    dicProcessColumn.Add(VALUE_COLUMN_REFERENCETABLENAME, ProcessColumnReferenceTableName);
                }
                return this.dicProcessColumn;
            }
        }

        /// <summary>
        /// 处理列信息
        /// </summary>
        private IDictionary<string, ProcessHandler<TableModal>> dicProcessTable = null;
        /// <summary>
        /// 获取处理列信息集合
        /// </summary>
        public IDictionary<string, ProcessHandler<TableModal>> DicProcessTable
        {
            get
            {
                if (dicProcessTable == null)
                {
                    dicProcessTable = new Dictionary<string, ProcessHandler<TableModal>>();
                    dicProcessTable.Add(VALUE_TABLE_TABLENAME, ProcessTableName);
                    dicProcessTable.Add(VALUE_TABLE_TABLEDESCRIPTION, ProcessTableDescription);
                    dicProcessTable.Add(VALUE_TABLE_REFERENCECOLUMN, ProcessTableReferenceColumn);
                }
                return this.dicProcessTable;
            }
        }

        #region TagSupport成员

        /// <summary>
        /// 标签名称
        /// </summary>
        public override string TagName
        {
            get { return "c:value"; }
        }

        /// <summary>
        /// 处理标签
        /// </summary>
        /// <param name="tagStr">标签文本</param>
        /// <param name="value">标签值</param>
        /// <returns></returns>
        public override string ProcessTag(string tagStr, object value)
        {
            try
            {
                string result = null;

                result = ProcessProperty(value);

                return result;

            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        #endregion

        /// <summary>
        /// 处理属性
        /// </summary>
        /// <param name="value">列实体</param>
        /// <returns></returns>
        private string ProcessProperty(object value)
        {
            try
            {
                StringBuilder sb = new StringBuilder();
                if (this.Properties.ContainsKey(ATTR_KEY)
                    && VariablesContainer.Variables.ContainsKey(this.Properties[ATTR_KEY]))
                {
                    sb.Append(VariablesContainer.Variables[this.Properties[ATTR_KEY]]);
                }
                else if (this.Properties.ContainsKey(ATTR_NAME))
                {
                    ProcessPropertyName(sb, value);
                }

                if (sb.Length > 0)
                {
                    if (this.Properties.ContainsKey(ATTR_LENGTH)
                        && DicProcessProperties.ContainsKey(ATTR_LENGTH))
                    {
                        DicProcessProperties[ATTR_LENGTH].Invoke(sb, value);
                    }
                    if (this.Properties.ContainsKey(ATTR_REPLACE)
                        && DicProcessProperties.ContainsKey(ATTR_REPLACE))
                    {
                        DicProcessProperties[ATTR_REPLACE].Invoke(sb, value);
                    }
                    if (this.Properties.ContainsKey(ATTR_PREFIX)
                        && DicProcessProperties.ContainsKey(ATTR_PREFIX))
                    {
                        DicProcessProperties[ATTR_PREFIX].Invoke(sb, value);
                    }
                    if (this.Properties.ContainsKey(ATTR_SUFFIX)
                        && DicProcessProperties.ContainsKey(ATTR_SUFFIX))
                    {
                        DicProcessProperties[ATTR_SUFFIX].Invoke(sb, value);
                    }
                }
                return sb.ToString();
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// 处理Name属性
        /// </summary>
        /// <param name="sb"></param>
        /// <param name="value"></param>
        private void ProcessPropertyName(StringBuilder sb, object value)
        {
            try
            {
                if (!this.Properties.ContainsKey(ATTR_NAME))
                {
                    return;
                }
                string property = this.Properties[ATTR_NAME].ToLower();
                if (value is ColumnModal)
                {
                    DicProcessColumn[property].Invoke(sb, value as ColumnModal);
                    //sb.Append(ProcessColumn(property, value as ColumnModal));
                }
                else if (value is TableModal)
                {
                    DicProcessTable[property].Invoke(sb, value as TableModal);
                    //sb.Append(ProcessTable(property, value as TableModal));
                }
                else
                {
                    sb.Append(property);
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }


        #region Process Property

        /// <summary>
        /// 处理前缀
        /// </summary>
        /// <param name="sb">StringBuilder</param>
        private void ProcessPrefix(StringBuilder sb, object value)
        {
            try
            {
                if (this.Properties.ContainsKey(ATTR_PREFIX))
                {
                    sb.Insert(0, this.Properties[ATTR_PREFIX]);
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// 处理后缀
        /// </summary>
        /// <param name="sb">StringBuilder</param>
        private void ProcessSuffix(StringBuilder sb, object value)
        {
            try
            {
                if (this.Properties.ContainsKey(ATTR_SUFFIX))
                {
                    sb.Append(this.Properties[ATTR_SUFFIX]);
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// 处理长度
        /// </summary>
        /// <param name="sb">StringBuilder</param>
        private void ProcessLength(StringBuilder sb, object value)
        {
            try
            {
                if (this.Properties.ContainsKey(ATTR_LENGTH)
                    && sb.Length > 0)
                {
                    int removeLength = 0;
                    if (Int32.TryParse(this.Properties[ATTR_LENGTH], out removeLength))
                    {
                        removeLength = sb.Length + removeLength;
                        sb.Remove(removeLength, sb.Length - removeLength);
                    }
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// 处理替换
        /// </summary>
        /// <param name="sb">StringBuilder</param>
        private void ProcessReplace(StringBuilder sb, object value)
        {
            try
            {
                if (this.Properties.ContainsKey(ATTR_REPLACE))
                {
                    string[] replaces = this.Properties[ATTR_REPLACE].Split(';');
                    foreach (string replace in replaces)
                    {
                        string[] param = replace.Split(',');
                        if (param.Length == 2)
                        {
                            sb.Replace(param[0], param[1]);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// 处理属性——RULE命名规则
        /// </summary>
        /// <param name="sb">StringBuilder</param>
        private void ProcessRules(StringBuilder sb, object value)
        {
            try
            {
                if (this.Properties.ContainsKey(ATTR_RULE))
                {
                    string ruleValue = this.Properties[ATTR_RULE];
                    if (dicProcessProperties.ContainsKey(ruleValue))
                    {
                        this.DicProcessProperties[ruleValue].Invoke(sb, value);
                    }
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        #endregion


        #region Process Rules Values

        /// <summary>
        /// 处理规则——Upper
        /// </summary>
        /// <param name="sb">StringBuilder</param>
        private void ProcessRulesUpper(StringBuilder sb, object value)
        {
            string tmp = sb.ToString().ToUpper();
            sb.Remove(0, sb.Length);
            sb.Append(tmp);
        }

        /// <summary>
        /// 处理规则——Lower
        /// </summary>
        /// <param name="sb">StringBuilder</param>
        private void ProcessRulesLower(StringBuilder sb, object value)
        {
            string tmp = sb.ToString().ToLower();
            sb.Remove(0, sb.Length);
            sb.Append(tmp);
        }

        /// <summary>
        /// 处理规则——Camel
        /// </summary>
        /// <param name="sb">StringBuilder</param>
        private void ProcessRulesCamel(StringBuilder sb, object value)
        {
            string tmp = sb.ToString();
            string first = tmp[0].ToString().ToLower();
            tmp = tmp.Remove(0, 1).Insert(0, first);
            sb.Remove(0, sb.Length);
            sb.Append(tmp);
        }

        /// <summary>
        /// 处理规则——Pascal
        /// </summary>
        /// <param name="sb">StringBuilder</param>
        private void ProcessRulesPascal(StringBuilder sb, object value)
        {
            string tmp = sb.ToString();
            string first = tmp[0].ToString().ToUpper();
            tmp = tmp.Remove(0, 1).Insert(0, first);
            sb.Remove(0, sb.Length);
            sb.Append(tmp);
        }

        #endregion


        #region Process Column Property

        /// <summary>
        /// 处理列名
        /// </summary>
        /// <param name="sb">StringBuilder</param>
        /// <param name="value">值</param>
        private void ProcessColumnName(StringBuilder sb, ColumnModal value)
        {
            try
            {
                if (this.Properties.ContainsKey(ATTR_TYPE))
                {
                    if (this.Properties[ATTR_TYPE] == VALUE_BASIC)
                    {
                        // 加载基本类型，跳过引用类型
                        if (value.ReferenceTableName == null)
                        {
                            sb.Append(value.ColumnName);
                        }
                    }
                    else if (this.Properties[ATTR_TYPE] == VALUE_REFERENCE)
                    {
                        // 加载引用类型，跳过基本类型
                        if (value.ReferenceColumnName != null)
                        {
                            sb.Append(value.ReferenceColumnName);
                        }
                    }
                }
                else
                {
                    sb.Append(value.ColumnName);
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// 处理列类型
        /// </summary>
        /// <param name="sb">StringBuilder</param>
        /// <param name="value">列值</param>
        private void ProcessColumnType(StringBuilder sb, ColumnModal value)
        {
            try
            {
                // 如果要求加载的是REFERENCE（引用数据类型），则使用引用类型
                if (this.Properties.ContainsKey(ATTR_TYPE))
                {
                    if (this.Properties[ATTR_TYPE] == VALUE_BASIC)
                    {
                        // 加载基本类型，跳过引用类型
                        if (value.ReferenceTableName == null)
                        {
                            string type = DataTypeSupport.UseDataType.DateTypes.ContainsKey(value.ColumnType)
                                ? DataTypeSupport.UseDataType.DateTypes[value.ColumnType]
                                : value.ColumnType;
                            sb.Append(type);
                        }
                    }
                    else if (this.Properties[ATTR_TYPE] == VALUE_REFERENCE)
                    {
                        // 加载引用类型，跳过基本类型
                        if (value.ReferenceTableName != null)
                        {
                            sb.Append(value.ReferenceTableName);
                        }
                    }
                    else if (this.Properties[ATTR_TYPE] == VALUE_ORIGINAL)
                    {
                        sb.Append(value.ColumnType);
                    }
                }
                else
                {
                    string type = DataTypeSupport.UseDataType.DateTypes.ContainsKey(value.ColumnType)
                                ? DataTypeSupport.UseDataType.DateTypes[value.ColumnType]
                                : value.ColumnType;
                    sb.Append(type);
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// 处理列描述
        /// </summary>
        /// <param name="sb">StringBuilder</param>
        /// <param name="value">列值</param>
        private void ProcessColumnDescription(StringBuilder sb, ColumnModal value)
        {
            try
            {
                sb.Append(value.Description.Length == 0 ? "未知" : value.Description);
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// 处理列引用表名
        /// </summary>
        /// <param name="sb">StringBuilder</param>
        /// <param name="value">列值</param>
        private void ProcessColumnReferenceTableName(StringBuilder sb, ColumnModal value)
        {
            sb.Append(value.ReferenceTableName);
        }

        /// <summary>
        /// 处理列长度
        /// </summary>
        /// <param name="sb">StringBuilder</param>
        /// <param name="value">列值</param>
        private void ProcessColumnLength(StringBuilder sb, ColumnModal value)
        {
            sb.Append(value.Length);
        }

        /// <summary>
        /// 处理列类型
        /// </summary>
        /// <param name="sb">StringBuilder</param>
        /// <param name="value">列值</param>
        private void ProcessColumnTableName(StringBuilder sb, ColumnModal value)
        {
            sb.Append(value.TableName);
        }

        #endregion


        #region Process Table Property

        /// <summary>
        /// 处理表名称
        /// </summary>
        /// <param name="sb">StringBuilder</param>
        /// <param name="value">表信息</param>
        private void ProcessTableName(StringBuilder sb, TableModal value)
        {
            sb.Append(value.TableName);
        }

        /// <summary>
        /// 处理表名称
        /// </summary>
        /// <param name="sb">StringBuilder</param>
        /// <param name="value">表信息</param>
        private void ProcessTableDescription(StringBuilder sb, TableModal value)
        {
            sb.Append(value.TableDescription);
        }

        /// <summary>
        /// 处理表名称
        /// </summary>
        /// <param name="sb">StringBuilder</param>
        /// <param name="value">表信息</param>
        private void ProcessTableReferenceColumn(StringBuilder sb, TableModal value)
        {
            sb.Append(value.ReferenceColumnName);
        }

        #endregion

    }
}